/*
 * Floor.cpp
 *
 *  Created on: 22/04/2012
 *      Author: alex
 */


#include "Floor.h"


using namespace std;

Floor::Floor(std::string pipePath, std::string keyGeneratorPath, int floorId, int floorAmmount)
{
	m_floorId = floorId;
	m_floorAmmount = floorAmmount;

	m_personQueue = new PassengerQueue(pipePath,keyGeneratorPath,floorId,
									   PassengerQueue::PRODUCER_END);

	m_personQueue->open();
}

Floor::~Floor()
{
	if(m_personQueue != NULL)
		delete m_personQueue;
}

void Floor::stopGeneratingPassengers()
{
    m_doGeneratePassengers = false;
}

void Floor::stopSimulation()
{
    m_doRun = false;
}

// ToDo: Habilitar estos logs (se podría hacer parametrizable (desde el programa principal) el hecho de que los pisos muestren o no la info de debug, tipo -D building (mensajes de debug solo del building), -D floor (solo mensajes de los pisos), -D o -D all (ambos mensajes de debug)
void Floor::startSimulation()
{
	srand ( time(NULL) +m_floorId);

	m_doRun =true;
	m_doGeneratePassengers = true;

	ElevatorPassenger passenger;
    while(m_doRun)
    {
    	//CLogger::log("Floor waiting",CLogger::DEBUG);

        if(m_doGeneratePassengers)
        {
            //Genero un pasajero
            passenger = generateRandomPassenger();

            CLogger::log("Passenger generated in floor: "+StringUtils::NumberToString(m_floorId)+
                    " with destination floor: "+StringUtils::NumberToString(passenger.getDestination())+".",LogLevelEnum::DEBUG);

            //Pongo el pasajero en la queue
            m_personQueue->pushPassenger(passenger);
        }
        else
        {
            sleep(1);
        }

//    	CLogger::log("The Passenger is waiting the elevator.",CLogger::DEBUG);
    }
}

ElevatorPassenger Floor::generateRandomPassenger()
{
	if(m_floorAmmount == UNDEFINED || m_floorId == UNDEFINED)
		throw new std::exception;

	ElevatorPassenger passenger;

	float sleepTime = ((float) rand() *MAX_PASSENGER_DELAY)/ (float) RAND_MAX ;
//	float passengerWeight = ((float) rand()/ (float) RAND_MAX) *
//								ElevatorPassenger::PASSENGER_WEIGHT_VARIANCE +
//								ElevatorPassenger::MINIMUM_PASSENGER_WEIGHT;
	float passengerWeight = ElevatorPassenger::DEFAULT_WEIGHT;


	FloorIdentifier passengerDestination;

	//Repito el ciclo si se da que el destino es igual al piso actual
	do{
		passengerDestination =((float) rand()/ (float) RAND_MAX) *m_floorAmmount;
	}
	while(passengerDestination == m_floorId);

	passenger.setDestination(passengerDestination);

	passenger.setWeight(passengerWeight);

	sleep(sleepTime);

	return passenger;
}
